package com.vf.cloud.pass.mvc.sys.controller;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.kit.StrKit;
import com.vf.cloud.pass.common.constant.SecurityConstant;
import com.vf.cloud.pass.common.domain.sys.Role;
import com.vf.cloud.pass.common.domain.sys.User;
import com.vf.cloud.pass.common.service.IToken;
import com.vf.cloud.pass.common.util.DateUtil;
import com.vf.cloud.pass.common.util.EncryptUtil;
import com.vf.cloud.pass.common.util.JWTUtil;
import com.vf.cloud.pass.common.util.R;
import com.vf.cloud.pass.common.util.RsaUtil;
import com.vf.cloud.pass.common.util.UuidUtil;
import com.vf.cloud.pass.common.vo.TokenVo;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@RestController
@RequestMapping("/")
public class LoginController {

	private final StringRedisTemplate redisTemplate;
	private final IToken tokenImpl;


	@RequestMapping(value = "login", method = RequestMethod.POST)
	public R<TokenVo> login(HttpServletRequest request, @RequestBody String param)
			throws NoSuchAlgorithmException, UnsupportedEncodingException {
		JSONObject json = JSONObject.parseObject(param);
		String username = json.getString("username");
		String password = json.getString("password");

		try {
			username = RsaUtil.decrypt(username, SecurityConstant.PRIVATE_KEY);
			password = RsaUtil.decrypt(password, SecurityConstant.PRIVATE_KEY);
		} catch (Exception e) {
			e.printStackTrace();
			return R.failed("解密登录信息失败!");
		}

		User user = User.dao.findbyUsername(username);
		if (user == null) {
			return R.failed("用户名或密码错误.");
		}

		if (!EncryptUtil.matches(password, user.getPassword())) {
			return R.failed("用户名或密码错误.");
		}
		String token = JWTUtil.generateToken(user.getId(), user.getUsername());
		redisTemplate.opsForValue().set(token, JSONObject.toJSONString(user), JWTUtil.getExpiresAt(token).getTime(),
				TimeUnit.MILLISECONDS);
		return R.ok(new TokenVo(SecurityConstant.TOKEN_SPLIT + token));
	}

	@RequestMapping(value = "logout", method = RequestMethod.GET)
	public R<String> logout(HttpServletRequest request) {
		try {
			String token = request.getHeader(SecurityConstant.HEADER);
			token = token.replace(SecurityConstant.TOKEN_SPLIT, "");
			redisTemplate.delete(token);
			return R.ok("用户已经注销！");
		} catch (Exception e) {
			return R.ok("用户已经注销！");
		}
	}

	@RequestMapping(value = "TokenExpired", method = RequestMethod.GET)
	public R<String> TokenExpired(HttpServletRequest request) {
		return R.failed(10042, "会话过期，请重新登录！");
	}

	@RequestMapping(value = "info", method = RequestMethod.GET)
	public R<Map<String, Object>> info(HttpServletRequest request) {
		try {
			String token = request.getHeader(SecurityConstant.HEADER);
			token = token.replace(SecurityConstant.TOKEN_SPLIT, "");
			String userId = JWTUtil.getClainByName(token, "userId").asString();

			User user = User.dao.findById(userId);
			if (user != null) {
				Map<String, Object> userInfoVo = new HashMap<String, Object>();
				userInfoVo.put("id", user.getId());
				userInfoVo.put("username", user.getUsername());
				userInfoVo.put("name", user.getName());
				userInfoVo.put("isSubAccount", user.getIsSubAccount());
				return R.ok(userInfoVo);
			}
			return R.failed(10042, "会话过期，请重新登录！");
		} catch (Exception e) {
			return R.failed(10042, "会话过期，请重新登录！");
		}
	}

	@RequestMapping(value = "reg", method = RequestMethod.POST)
	public R<String> reg(HttpServletRequest request, @RequestBody String param)
			throws NoSuchAlgorithmException, UnsupportedEncodingException {
		JSONObject json = JSONObject.parseObject(param);
		String phone = json.getString("phone");
		String name = json.getString("name");
		String password = json.getString("password");
		String orgName = json.getString("orgName");
		String code = json.getString("code");

		try {
			phone = RsaUtil.decrypt(phone, SecurityConstant.PRIVATE_KEY);
			name = RsaUtil.decrypt(name, SecurityConstant.PRIVATE_KEY);
			password = RsaUtil.decrypt(password, SecurityConstant.PRIVATE_KEY);
			orgName = RsaUtil.decrypt(orgName, SecurityConstant.PRIVATE_KEY);
			code = RsaUtil.decrypt(code, SecurityConstant.PRIVATE_KEY);
		} catch (Exception e) {
			e.printStackTrace();
			return R.failed("解密信息失败!");
		}

		String redisCodeKey = SecurityConstant.VERIFY_CODE_PREFIX + phone;
		if(tokenImpl.isExpire(redisCodeKey)) {
			return R.failed("验证码过期.");
		}

		String payload = redisTemplate.opsForValue().get(redisCodeKey);
		if (StrKit.isBlank(payload)) {
			redisTemplate.delete(redisCodeKey);
			return R.failed("验证码无效.");
		}

		if (!StrKit.equals(code, payload)) {
			return R.failed("验证码无效.");
		}

		User user = User.dao.findbyUsername(phone);
		if (user != null) {
			return R.failed("手机号已被注册.");
		}
		user = new User();
		user.setId(UuidUtil.getUUID());
		user.setName(name);
		user.setUsername(phone);
		user.setPhone(phone);
		user.setOrgName(orgName);
		user.setOrgId(user.getId());
		user.setPassword(EncryptUtil.encrypt(password));
		user.setCreateTime(DateUtil.getLocalDateTime());
		if (user.save()) {
			try {
				Role role = Role.dao.findFirst("SELECT * FROM "+Role.TABLE_NAME+" WHERE CODE = 'customer' ");
				if(role!=null) {
					User.saveRoleIds(user.getId(), role.getId());
				}
			} catch (Exception e) {
//				e.printStackTrace();
			}
			return R.ok("注册成功.");
		} else {
			return R.failed("注册失败.");
		}
	}

	@RequestMapping(value = "updatePwd", method = RequestMethod.POST)
	public R<String> forget(HttpServletRequest request, @RequestBody String param)
			throws NoSuchAlgorithmException, UnsupportedEncodingException {
		JSONObject json = JSONObject.parseObject(param);
		String phone = json.getString("phone");
		String password = json.getString("password");
		String code = json.getString("code");

		try {
			phone = RsaUtil.decrypt(phone, SecurityConstant.PRIVATE_KEY);
			password = RsaUtil.decrypt(password, SecurityConstant.PRIVATE_KEY);
			code = RsaUtil.decrypt(code, SecurityConstant.PRIVATE_KEY);
		} catch (Exception e) {
			e.printStackTrace();
			return R.failed("解密信息失败!");
		}

		User user = User.dao.findbyUsername(phone);
		if (user == null) {
			return R.failed("手机号不存在.");
		}

		String redisCodeKey = SecurityConstant.VERIFY_CODE_PREFIX + phone;
		
		if(tokenImpl.isExpire(redisCodeKey)) {
			return R.failed("验证码过期.");
		}
		

		String payload = redisTemplate.opsForValue().get(redisCodeKey);
		if (StrKit.isBlank(payload)) {
			redisTemplate.delete(redisCodeKey);
			return R.failed("验证码无效.");
		}

		if (!StrKit.equals(code, payload)) {
			return R.failed("验证码无效.");
		}
		user.setPassword(EncryptUtil.encrypt(password));
		user.setUpdateTime(DateUtil.getLocalDateTime());
		if (user.update()) {
			return R.ok("密码修改成.");
		} else {
			return R.failed("密码修改成.");
		}
	}

	@GetMapping(value = "/code/{phone}")
	@ResponseBody
	public R<String> code(@PathVariable String phone) {
		String code = UuidUtil.randomCode() + "";
		String redisCodeKey = SecurityConstant.VERIFY_CODE_PREFIX + phone;
		redisTemplate.opsForValue().set(redisCodeKey, code,
				new Date(System.currentTimeMillis() + SecurityConstant.ERIFY_CODE_EXPIRATION_TIME).getTime(),
				TimeUnit.MILLISECONDS);
		return R.ok("短信发送成功，5分钟内有效.", code);
	}

}